//
// <copyright file="FormatErrors.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
using System;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
namespace Microsoft.Samples.ServiceHosting.HelloFabric
{
    public class Format
    {
        public static void KeyValueDict(TextWriter strm, IDictionary<string, string> dict)
        {
            var query =
                from kv in dict
                orderby kv.Key
                where kv.Value != null
                select new
                {
                    len = kv.Key.Length,
                    key = kv.Key,
                    value = kv.Value
                };
            var lenMax =
                query.Max(item => item.len);

            foreach (var item in query)
            {
                strm.WriteLine("{0}: {1}", item.key.PadLeft(lenMax),
                                          item.value);
            }
        }

        public static string HttpRequestAsText(System.Web.HttpRequest req)
        {
            var dict = new SortedDictionary<string, string>();
            dict.Add("RawUrl", req.RawUrl);
            dict.Add("HttpMethod", req.HttpMethod);
            if (req.Headers != null)
            {
                StringBuilder sbuf = new StringBuilder();

                for (int i = 0; i < req.Headers.Count; i++)
                {
                    string key = req.Headers.GetKey(i);
                    string val = req.Headers.Get(i);
                    sbuf.AppendLine();
                    sbuf.AppendFormat("\t{0}: {1}", key, val);
                }
                dict.Add("Headers", sbuf.ToString());
            }
            StringWriter wr = new StringWriter();
            KeyValueDict(wr, dict);
            wr.Close();
            return wr.ToString();
        }

        public static string MethodBase(MethodBase method)
        {
            StringBuilder sbuf = new StringBuilder();
            sbuf.AppendFormat("{0}.{1}(",
                    method.DeclaringType.FullName,
                    method.Name);
            ParameterInfo[] paramInfo = method.GetParameters();
            for (int p = 0; p < paramInfo.Length; p++)
            {
                sbuf.AppendFormat("{0} {1}", paramInfo[p].ParameterType.FullName, paramInfo[p].Name);
                if (p + 1 < paramInfo.Length)
                {
                    sbuf.Append(", ");
                }
            }
            sbuf.Append(")");
            return sbuf.ToString();
        }

        public static string StackTrace(StackTrace stackTrace)
        {
            StringBuilder sbuf = new StringBuilder();
            foreach (StackFrame frame in stackTrace.GetFrames())
            {
                MethodBase method = frame.GetMethod();
                int ilOffset = frame.GetILOffset();

                string fullName = method.DeclaringType.FullName + "." + method.Name;
                string sourceLocation = "";
                if (ilOffset > 0)
                {
                    sourceLocation += "IL offset " + ilOffset;
                }
                sbuf.AppendLine();
                sbuf.AppendFormat("  {0} at {1}",
                    MethodBase(method),
                    sourceLocation);
            }
            return sbuf.ToString();
        }

        public static string ExceptionAsText(Exception ex)
        {
            var dict = new SortedDictionary<string, string>();
            dict.Add("Message", ex.Message);
            dict.Add("Name", ex.GetType().FullName);
            dict.Add("HelpLink", ex.HelpLink);
            dict.Add("Source", ex.Source);
            StackTrace stackTrace = new StackTrace(ex, true);
            dict.Add("Stack-Trace", StackTrace(stackTrace));
            if (ex.InnerException != null)
            {
                dict.Add("InnerException", ex.InnerException.ToString());
            }
            if (ex.Data != null)
            {
                foreach (DictionaryEntry entry in ex.Data)
                {
                    if (entry.Key != null && entry.Value != null)
                    {
                        dict.Add("Data-" + entry.Key.ToString(),
                            entry.Value.ToString());
                    }
                }
            }
            StringWriter wr = new StringWriter();
            KeyValueDict(wr, dict);
            wr.Close();
            return wr.ToString();
        }
    }
}
